﻿namespace Ex03.GarageManagementSystem.ConsoleUI
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    public class GarageManagerUI
    {
        private const bool k_ValidInput = true;
        private GarageLogic.Garage m_Garage;

        public GarageManagerUI()
        {
            m_Garage = new GarageLogic.Garage();
        }
        
        public void StartProgram()
        {
            bool exit = false;
            
            while (!exit)
            {
                ShowMainMenu();
                HandleUsersChoice(ref exit);
            }
        }

        public void ShowMainMenu()
        {
            StringBuilder menu = new StringBuilder();

            menu.Append("What would you like to do?" + System.Environment.NewLine + "Type the number of the option:" + System.Environment.NewLine);

            menu.Append("1) Create new customer." + System.Environment.NewLine + "2) Present the vehicles in the Garage." + System.Environment.NewLine + "3) Change a costumer's vehicle status." + System.Environment.NewLine);
            menu.Append("4) Inflate a Customer's vehicle wheels to maximum." + System.Environment.NewLine + "5) Refuel a Costumer's vehicle." + System.Environment.NewLine + "6) Recharge a customer's elcetric vehicle." + System.Environment.NewLine);
            menu.Append("7) Show a costumer's detailes." + System.Environment.NewLine + "8) Exit");

            System.Console.Clear();
            System.Console.WriteLine(menu);
        }

        /// <summary>
        /// This function handles the user choice from the main menu, and activates the corresponding function 
        /// </summary>
        /// <param name="i_Exit">A boolean parameter used as an exit flag from program</param>
        public void HandleUsersChoice(ref bool i_Exit)
        {
            eMenuOptions usersChoice = eMenuOptions.Exit;
            try
            {
                usersChoice = (eMenuOptions)Enum.Parse(typeof(eMenuOptions), System.Console.ReadLine());
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.Message);
                System.Console.WriteLine("Press any key to continue");
                System.Console.ReadLine();
                StartProgram();
            }

            try
            {
                switch (usersChoice)
                {
                    case eMenuOptions.AddNewCustomer:
                        AddNewCustomer();
                        break;
                    case eMenuOptions.DisplayVehiclesLicenseNumbers:
                        DisplayVehicleListPrintOptions();
                        break;
                    case eMenuOptions.ChangeVehicleStatus:
                        ChangeVehicleStatus();
                        break;
                    case eMenuOptions.InflateWheels:
                        InflateWheels();
                        break;
                    case eMenuOptions.RefuelVehicle:
                        RechargeCustomersVehicle(eEnergySourceType.Fueled);
                        break;
                    case eMenuOptions.RechargeVehicle:
                        RechargeCustomersVehicle(eEnergySourceType.Electric);
                        break;
                    case eMenuOptions.ShowVehicleDetails:
                        GetVehicleData();
                        break;
                    case eMenuOptions.Exit:
                        i_Exit = true;
                        break;
                    default:
                        throw new FormatException("Wrong menu choice, please select number between 1 and 8");
                }
            }
            catch(FormatException ex)
            {
                System.Console.WriteLine(ex.Message);
                System.Console.WriteLine("Press any key to continue");
                System.Console.ReadLine();
                StartProgram();
            }
        }
        
        private void InflateWheels()
        {
            string vehicleLicenseNumber;
            System.Console.WriteLine("Please enter vehicle license number to inflate wheels to: ");
            vehicleLicenseNumber = System.Console.ReadLine();
            try
            {
                m_Garage.InflateWheelsToMaximum(vehicleLicenseNumber);
                System.Console.WriteLine("Vehicle number " + vehicleLicenseNumber + "wheels has been inflated to maximum succesfully");
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.Message);
                System.Console.WriteLine("Please press any key to continue");
                System.Console.ReadLine();
                InflateWheels();
            }
        }

        private void ChangeVehicleStatus()
        {
            string licenseNumber;
            GarageLogic.Customer.eVehicleStatus statusToChange;

            System.Console.WriteLine("Please enter license number:" + System.Environment.NewLine);
            licenseNumber = System.Console.ReadLine();

            if (m_Garage.IsVehicleInGarage(licenseNumber))
            {
                System.Console.WriteLine("Please choose the status to define for vehicle:");
                System.Console.WriteLine("1) In repair");
                System.Console.WriteLine("2) Fixed");
                System.Console.WriteLine("3) Paid");

                statusToChange = (GarageLogic.Customer.eVehicleStatus)Enum.Parse(typeof(GarageLogic.Customer.eVehicleStatus), System.Console.ReadLine());

                m_Garage.UpdateVehicleStatus(licenseNumber, statusToChange);
            }
            else
            {
                System.Console.WriteLine("Sorry, but this license number isn't in the garage." + System.Environment.NewLine);
            }
        }

        public void AddNewCustomer()
        {
            GarageLogic.Customer customerToAdd = new GarageLogic.Customer();
            
            System.Console.WriteLine("Please enter costumer's detailes:" + System.Environment.NewLine);
            System.Console.WriteLine("Please enter costumer's name: ");
            customerToAdd.OwnerName = System.Console.ReadLine();
            System.Console.WriteLine(System.Environment.NewLine + "Please enter costumers phone number: ");
            customerToAdd.PhoneNumber = System.Console.ReadLine();
            
            customerToAdd.VehicleStatus = GarageLogic.Customer.eVehicleStatus.InRepair;

            if (!HandleVehicleDetails(ref customerToAdd))
            {
                m_Garage.AddNewCustomer(customerToAdd);
            }
        }

        private bool HandleVehicleDetails(ref GarageLogic.Customer i_CustomerToAdd)
        {
            GarageLogic.VehicleGenerator generator = new GarageLogic.VehicleGenerator();

            GarageLogic.VehicleGenerator.eVehicleType UsersVehicleTypeChoice = GarageLogic.VehicleGenerator.eVehicleType.ElectricCar;

            System.Console.WriteLine(System.Environment.NewLine + "Please enter costumer's vehicle details:");
            System.Console.WriteLine("Please choose the vehicle type: ");
            PrintVehicleTypes(generator);
            try
            {
                UsersVehicleTypeChoice = (GarageLogic.VehicleGenerator.eVehicleType)Enum.Parse(typeof(GarageLogic.VehicleGenerator.eVehicleType), System.Console.ReadLine());
            }
            catch(FormatException ex)
            {
                System.Console.WriteLine(ex.Message);
                System.Console.WriteLine("Please press any key to continue");
                System.Console.ReadLine();
                HandleVehicleDetails(ref i_CustomerToAdd);
            }

            i_CustomerToAdd.CustomerVehicle = generator.CreateNewVehicle(UsersVehicleTypeChoice);

            return HandleVehicleDetailsAux(ref i_CustomerToAdd);
        }

        private bool HandleVehicleDetailsAux(ref GarageLogic.Customer i_customerToUpdate)
        {
            List<string> vehicleDetails = new List<string>();
            bool foundInGarage = false;

            System.Console.WriteLine("Enter the license number of the vehicle: ");            
            vehicleDetails.Add(System.Console.ReadLine());
            if (m_Garage.IsVehicleInGarage(vehicleDetails[0]))
            {
                m_Garage.UpdateVehicleStatus(vehicleDetails[0], GarageLogic.Customer.eVehicleStatus.InRepair);
                System.Console.WriteLine("the vehicle is already in the garage, it's in repair.");
                foundInGarage = true;
            }
            else
            {
                string currentCapacity = string.Empty;
                string currentWheelPressure = string.Empty;
                float maxValue = i_customerToUpdate.CustomerVehicle.EnergySource.MaxEnergyCapacity;
                bool IsValidInput = !k_ValidInput;
                System.Console.WriteLine("Enter the model name of the vehicle: ");
                vehicleDetails.Add(System.Console.ReadLine());

                while (!IsValidInput)
                {
                    if (i_customerToUpdate.CustomerVehicle.EnergySource is GarageLogic.Fueled)
                    {
                        System.Console.WriteLine("Enter the current capacity of the fuel tank of the vehicle (between 0 and " + maxValue + "): ");
                    }
                    else
                    {
                        System.Console.WriteLine("Enter the current capacity of the battery of the vehicle (between 0 and " + maxValue + "): ");
                    }

                    currentCapacity = System.Console.ReadLine();
                    if (int.Parse(currentCapacity) <= maxValue && int.Parse(currentCapacity) >= 0)
                    {
                        IsValidInput = k_ValidInput;
                    }
                    else
                    {
                        System.Console.WriteLine("Current capacity is not a valid number, please try again");
                    }
                }

                vehicleDetails.Add(currentCapacity);
                System.Console.WriteLine("Enter the wheel's manufacturer: ");
                vehicleDetails.Add(System.Console.ReadLine());
                System.Console.WriteLine("Enter the wheel's current air pressure: ");
                vehicleDetails.Add(System.Console.ReadLine());
                HandleSpecialVhicleFeatures(ref vehicleDetails, i_customerToUpdate);
                try
                {
                    i_customerToUpdate.CustomerVehicle.UpdateVehicleDetails(vehicleDetails);
                }
                catch (Exception ex)
                {
                    System.Console.WriteLine(ex.Message);
                    System.Console.WriteLine("Press any key to continue");
                    System.Console.ReadLine();
                    HandleVehicleDetailsAux(ref i_customerToUpdate);
                }
            }

            return foundInGarage;
        }

        private void HandleSpecialVhicleFeatures(ref List<string> i_vehicleDetails, GarageLogic.Customer i_CustomerToUpdate)
        {
            List<string> specialFeatureList = new List<string>();
            specialFeatureList = m_Garage.ReturnSpecialVehicleFeatures(i_CustomerToUpdate.CustomerVehicle);

            foreach (string currentFeature in specialFeatureList)
            {
                System.Console.WriteLine("Please enter " + currentFeature + ":");
                i_vehicleDetails.Add(System.Console.ReadLine());
            }
        }

        private void PrintVehicleTypes(GarageLogic.VehicleGenerator i_Generator)
        {
            string[] VehicleTypes = i_Generator.ModelsNames;
            for(int i = 0; i < VehicleTypes.Length; i++)
            {
                System.Console.WriteLine(i + 1 + ") " + VehicleTypes[i]);
            }
        }

        private void DisplayVehicleListPrintOptions()
        {
            string usersChoice;
            System.Console.Clear();
            System.Console.WriteLine("Choose a way do display the cars in the garage:");
            System.Console.WriteLine("1) Display all the license numbers of the vehicles in the garage.");
            System.Console.WriteLine("2) Display license numbers by the vehicle status.");
            
            usersChoice = System.Console.ReadLine();
            if (usersChoice == "1")
            {
                DisplayAllVehicleLicenseNumbers();
            }
            else if (usersChoice == "2")
            {
                DisplayLicenseNumbersByStatus();
            }
            else
            {
                System.Console.WriteLine("Invalid choice, please try again");
                DisplayVehicleListPrintOptions();
            }
        }

        private void DisplayAllVehicleLicenseNumbers()
        {
            System.Console.Clear();
            System.Console.WriteLine(m_Garage.CreateCustomerLicenseNumberList());
            System.Console.WriteLine("Press any key to continue");
            System.Console.ReadLine();
        }

        private void DisplayLicenseNumbersByStatus()
        {
            string usersChoice;
            GarageLogic.Customer.eVehicleStatus VehicleStatus = GarageLogic.Customer.eVehicleStatus.InRepair;
            
            System.Console.WriteLine("Please choose a vehicle status to filtter by:");
            System.Console.WriteLine("1) In repair");
            System.Console.WriteLine("2) Fixed");
            System.Console.WriteLine("3) Paid");
            usersChoice = System.Console.ReadLine();
            try
            {
                switch (usersChoice)
                {
                    case "1":
                        {
                            VehicleStatus = GarageLogic.Customer.eVehicleStatus.InRepair;
                            break;
                        }

                    case "2":
                        {
                            VehicleStatus = GarageLogic.Customer.eVehicleStatus.Fixed;
                            break;
                        }

                    case "3":
                        {
                            VehicleStatus = GarageLogic.Customer.eVehicleStatus.Paid;
                            break;
                        }

                    default:
                        {
                            throw new FormatException("Invalid vehicle status, please try again");
                        }
                }
            }
            catch(FormatException ex)
            {
                System.Console.WriteLine(ex.Message);
                System.Console.WriteLine("Press any key to continue");
                System.Console.ReadLine();
                DisplayLicenseNumbersByStatus();
            }
            
            System.Console.Clear();
            System.Console.WriteLine(m_Garage.CreateCustomerLicenseNumberListByVehicleStatus(VehicleStatus));
            System.Console.WriteLine("Press any key to continue");
            System.Console.ReadLine();
        }

        /// <summary>
        /// This function allows the user to choose a vehicle by the license number and prints all of its details
        /// </summary>
        private void GetVehicleData()
        {
            System.Console.Clear();
            System.Console.WriteLine("Please enter the license number of the vehicle you wish to check: ");
            System.Console.WriteLine(m_Garage.CreateCustomerDataPrint(System.Console.ReadLine()));
            System.Console.WriteLine("Please press any key to continue");
            System.Console.ReadLine();
        }

        private void RechargeCustomersVehicle(eEnergySourceType i_EnergySource)
        {
            float i_amountToAdd;
            string LicenseNumber;
            GarageLogic.EnergySource.eEnergySourceType fuelType = GarageLogic.EnergySource.eEnergySourceType.Electricity;

            System.Console.WriteLine("Please Enter the license number of the vehicle:");
            LicenseNumber = System.Console.ReadLine();

            switch (i_EnergySource)
            {
                case eEnergySourceType.Electric:
                    {
                        System.Console.WriteLine("Please enter the amount of hour to recharge the battery:");
                        break;
                    }

                case eEnergySourceType.Fueled:
                    {
                        System.Console.WriteLine("Please enter the fuel type to add to the tank:");
                        System.Console.WriteLine("1) Soler" + System.Environment.NewLine + "2) Octan 95"  + System.Environment.NewLine + "3) Octan 96"  + System.Environment.NewLine + "4) Octan 98");
                        fuelType = (GarageLogic.EnergySource.eEnergySourceType)Enum.Parse(typeof(GarageLogic.EnergySource.eEnergySourceType), System.Console.ReadLine());
                        System.Console.WriteLine("Please enter the amount of fuel to add to the tank: ");
                        break;
                    }

                default:
                    {
                        break;
                    }
            }

            i_amountToAdd = float.Parse(System.Console.ReadLine());
            try
            {
                m_Garage.RechargeEnergySource(LicenseNumber, fuelType, i_amountToAdd);
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.Message);
                System.Console.WriteLine("Please try again");
                System.Console.ReadLine();
                System.Console.Clear();
                RechargeCustomersVehicle(i_EnergySource);
            }
        }

        public enum eEnergySourceType
        {
            Electric,
            Fueled
        }

        public enum eVehicleType
        {
            Car,
            Motorcycle,
            Truck
        }

        public enum eMenuOptions
        {
            AddNewCustomer = 1,
            DisplayVehiclesLicenseNumbers = 2,
            ChangeVehicleStatus = 3,
            InflateWheels = 4,
            RefuelVehicle = 5,
            RechargeVehicle = 6,
            ShowVehicleDetails = 7,
            Exit = 8
        }
    }
}
